﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Threading;
using System.Windows;
using System.ServiceModel.DomainServices.Client;

namespace MVVMS
{
    /// <summary>
    /// Standard ViewModel Implementation for MVVM-S implementation
    /// </summary>
    public class RIAViewModel : INotifyPropertyChanged
    {

        #region INotifyPropertyChanged Implementation

        public event PropertyChangedEventHandler PropertyChanged;
        protected void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        #endregion

        /// <summary>
        /// Sends any action to the UI thread, not needed for simple implementations,
        /// but useful when you use a timer or other background worker to
        /// to load data, etc.
        /// </summary>
        /// <param name="action"></param>
        protected void CallOnUI(Action action)
        {
            UIDispatcher.CallOnUI(action);
        }

        /// <summary>
        /// Override this Method in your ViewModel class to handle
        /// Operations with Errors
        /// </summary>
        /// <param name="opWithErr"></param>
        protected virtual void OnOperationError(OperationBase opWithErr)
        {

        }

        #region IsBusy And Request Tracking Implementation
        public bool IsBusy
        {
            get
            {
                if (busyOperations == null ||
                  busyOperations.Count == 0)
                    return false;
                return true;
            }
        }

        public String BusyMessage
        {
            get 
            {
                lock (operationsLock)
                {
                    if (busyOperations == null ||
                        busyOperations.Count == 0)
                        return String.Empty;
                    return busyOperations.First().Value;
                }
            }
        }

        Object operationsLock = new Object();
        Dictionary<OperationBase, String> busyOperations;
        
        protected void RegisterOperation(OperationBase operation, String Message)
        {
            if (busyOperations == null)
                busyOperations = new Dictionary<OperationBase, string>();
            busyOperations.Add(operation, Message);
            operation.Completed += new EventHandler(operation_Completed);
            if (busyOperations.Count == 1)
                RaisePropertyChanged("IsBusy");
            RaisePropertyChanged("BusyMessage");
        }

        private void operation_Completed(object sender, EventArgs e)
        {
            CallOnUI(() =>
            {
                OperationBase operation = (OperationBase)sender;
                if (operation.HasError)
                    OnOperationError(operation);
                operation.Completed -= new EventHandler(operation_Completed);
                busyOperations.Remove(operation);
                if (busyOperations.Count == 0)
                    RaisePropertyChanged("IsBusy");
                RaisePropertyChanged("BusyMessage");
            });
        }

        #endregion
    }
}
